package com.cellulam.framework.push.common;

import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;

/**
 * 3种类型的邮件 - text, html, mixed(附件)
 * <br>
 */
public class ContentMail {

    public static final String VARIABLE_FORMAT_PREFIX = "\\{\\{";
    public static final String VARIABLE_FORMAT_SUFFIX = "\\}\\}";

    public static final int TYPE_TEXT = 1;
    public static final int TYPE_HTML = 2;
    /**
     * 混合模式, 支持附件
     */
    public static final int TYPE_MIXED = 3;

    private int type;
    private String subject;
    private String content;
    private String templet;
    private String batchId;
    private boolean async;
    private MailCallback mailCallback = new MailCallback();
    private Map<String, String> params = Maps.newHashMap();
    private List<String> tos = new ArrayList<>();
    private List<File> attachments = new ArrayList<>();

    private ContentMail(int type) {
        this.type = type;
    }

    public static ContentMail createTextMail() {
        return new ContentMail(TYPE_TEXT);
    }

    public static ContentMail createHtmlMail() {
        return new ContentMail(TYPE_HTML);
    }

    /**
     * 混合模式, 支持附件
     *
     * @return
     */
    public static ContentMail createMixedMail() {
        return new ContentMail(TYPE_MIXED);
    }

    public boolean isText() {
        return this.type == TYPE_TEXT;
    }

    public boolean isHtml() {
        return this.type == TYPE_HTML;
    }

    public boolean isMixed() {
        return this.type == TYPE_MIXED;
    }

    public ContentMail async(boolean async) {
        this.async = async;
        return this;
    }

    public ContentMail setSubject(String subject) {
        this.subject = subject;
        return this;
    }

    public ContentMail setContent(String content) {
        this.content = content;
        return this;
    }

    public ContentMail setTemplet(String templet) {
        this.templet = templet;
        return this;
    }

    public ContentMail addTo(String toMail) {
        if (StringUtils.isNotBlank(toMail)) {
            tos.add(StringUtils.trim(toMail));
        }
        return this;
    }

    public ContentMail addTos(List<String> addedTos) {
        if (CollectionUtils.isNotEmpty(addedTos)) {
            addedTos.forEach(this::addTo);
        }
        return this;
    }

    public ContentMail addTos(String... addedTos) {
        if (ArrayUtils.isNotEmpty(addedTos)) {
            Stream.of(addedTos).forEach(this::addTo);
        }
        return this;
    }

    public ContentMail addParam(String key, String value) {
        params.put(key, value);
        return this;
    }

    /**
     * 增加分隔符分隔的邮件, 例如: <br>
     * zhangying@hujiang.com,zhengjian@hujiang.com
     *
     * @param tos
     * @param splitter
     * @return
     */
    public ContentMail addSplittedTos(String tos, String splitter) {
        Arrays.stream(tos.split(splitter))
                .filter(StringUtils::isNotBlank)
                .map(StringUtils::trim)
                .forEach(this::addTo);
        return this;
    }

    public ContentMail setTos(List<String> tos) {
        this.tos = tos;
        return this;
    }

    /**
     * 添加附件
     *
     * @param attach
     * @return
     */
    public ContentMail addAttachFile(File attach) {
        attachments.add(attach);
        return this;
    }

    public ContentMail setAttachFiles(List<File> attachFiles) {
        this.attachments = attachFiles;
        return this;
    }

    public ContentMail setSendSuccess(Consumer<String> consumer) {
        this.mailCallback.setSendSuccess(consumer);
        return this;
    }

    public ContentMail setSendFail(Consumer<Exception> consumer) {
        this.mailCallback.setSendFail(consumer);
        return this;
    }

    //
    public Integer getType() {
        return type;
    }

    public String getSubject() {
        return subject;
    }

    public String getContent() {
        if (StringUtils.isEmpty(content) && !StringUtils.isEmpty(templet)) {
            String finalContent = templet;
            for (String key : params.keySet()) {
                finalContent = finalContent.replaceAll(VARIABLE_FORMAT_PREFIX + key + VARIABLE_FORMAT_SUFFIX,
                        params.get(key));
            }
            return finalContent;
        }
        return content;
    }

    public List<String> getTos() {
        return tos;
    }

    public List<File> getAttachments() {
        return attachments;
    }

    public String getTemplet() {
        return templet;
    }

    public boolean isAsync() {
        return this.async;
    }

    public MailCallback getMailCallback() {
        return this.mailCallback;
    }
}
